Learn in 10 minutes

Learn in 10 minutes

Apprendre Go en 10 minutes

Go (également connu sous le nom de Golang) est un langage de programmation compilé et statiquement typé conçu chez Google. Il est connu pour sa simplicité, son efficacité et son excellent support pour la concurrence. Ce tutoriel vous aidera à apprendre rapidement la programmation en Go.

1. Écrire votre premier programme Go

Commençons par un programme simple. Créez un fichier nommé hello.go et entrez le code suivant :

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Sauvegardez le fichier et exécutez la commande suivante dans le terminal :

go run hello.go

Le résultat sera :

Hello, World!

Ce programme simple démontre la structure de base de Go :

  • package main déclare le nom du package
  • import "fmt" importe le package de format pour les opérations d’entrée/sortie
  • func main() est le point d’entrée du programme
  • fmt.Println() affiche du texte dans la console

2. Syntaxe de base

Go a une syntaxe claire et simple. Contrairement à Python, Go utilise des accolades {} pour définir les blocs de code et nécessite des points-virgules à la fin des instructions (bien qu’ils soient généralement insérés automatiquement).

// Ceci est un commentaire sur une seule ligne
fmt.Println("Hello, World!")

/*
Ceci est un commentaire multi-lignes
s'étendant sur plusieurs lignes
*/

Règles de syntaxe de base en Go :

  • Blocs de code : Définis par des accolades {}
  • Commentaires : Les commentaires sur une seule ligne commencent par //, les commentaires multi-lignes par /* */
  • Instructions : Se terminent par des points-virgules (insérés automatiquement)
  • Déclaration de package : Chaque fichier commence par une déclaration de package

3. Variables et types de données

Go est statiquement typé, ce qui signifie que vous devez déclarer les types de variables. Cependant, Go prend en charge l’inférence de type avec l’opérateur :=.

Méthodes de déclaration de variables :

// Déclaration de type explicite
var name string = "John"
var age int = 25

// Inférence de type
name := "John"
age := 25

// Déclaration multiple de variables
var x, y int = 10, 20
x, y := 10, 20

Principaux types de données de base de Go :

  • Types entiers : int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr
  • Types flottants : float32, float64
  • Chaîne de caractères : string
  • Booléen : bool
  • Types complexes : complex64, complex128

3.1 Types numériques

Go fournit divers types numériques pour différents cas d’utilisation :

// Types entiers
var age int = 25
var smallNumber int8 = 127
var largeNumber int64 = 9223372036854775807

// Types flottants
var temperature float32 = 36.5
var pi float64 = 3.14159265359

// Nombres complexes
var complexNum complex64 = 3 + 4i

3.2 Type chaîne de caractères

Les chaînes en Go sont des séquences d’octets et sont immuables :

// Déclaration de chaîne
var greeting string = "Hello, Go!"
name := "Alice"

// Opérations sur les chaînes
fmt.Println(len(greeting))        // Longueur de la chaîne
fmt.Println(greeting[0])          // Accéder au premier caractère (octet)
fmt.Println(greeting[0:5])        // Découpage de chaîne
fmt.Println(strings.ToUpper(name)) // Conversion en majuscules

3.3 Type booléen

Le type booléen a deux valeurs : true et false :

var isActive bool = true
var isComplete bool = false

// Opérations booléennes
result1 := true && false  // false
result2 := true || false  // true
result3 := !true          // false

4. Constantes

Les constantes sont déclarées en utilisant le mot-clé const et ne peuvent pas être modifiées :

const Pi = 3.14159
const MaxUsers = 1000

// Constantes multiples
const (
    StatusOK = 200
    StatusNotFound = 404
    StatusError = 500
)

// Constantes typées
const Version string = "1.0.0"

5. Structures de données

Go fournit plusieurs structures de données intégrées pour stocker et manipuler des données.

5.1 Tableaux

Les tableaux sont des séquences de taille fixe d’éléments du même type :

// Déclaration de tableau
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
names := [3]string{"Alice", "Bob", "Charlie"}

// Accès aux éléments
fmt.Println(numbers[0])  // 1
numbers[0] = 10         // Modifier l'élément

// Longueur du tableau
fmt.Println(len(numbers)) // 5

5.2 Tranches (Slices)

Les tranches sont des tableaux dynamiques qui peuvent grandir et rétrécir :

// Déclaration de tranche
numbers := []int{1, 2, 3, 4, 5}
var emptySlice []int

// Création de tranches à partir de tableaux
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4]  // [2, 3, 4]

// Opérations sur les tranches
numbers = append(numbers, 6)      // Ajouter un élément
numbers = append(numbers, 7, 8, 9) // Ajouter plusieurs éléments

// Capacité et longueur de la tranche
fmt.Println(len(numbers)) // Longueur : 9
fmt.Println(cap(numbers)) // Capacité : 10 (peut varier)

5.3 Maps (Tableaux associatifs)

Les maps sont des collections non ordonnées de paires clé-valeur :

// Déclaration de map
student := map[string]interface{}{
    "name": "John",
    "age":  20,
    "major": "Computer Science",
}

// Déclaration alternative
var scores map[string]int = make(map[string]int)
scores["math"] = 95
scores["science"] = 88

// Accès et modification
fmt.Println(student["name"])
student["age"] = 21
student["gpa"] = 3.8

// Accès sécurisé
if phone, exists := student["phone"]; exists {
    fmt.Println(phone)
} else {
    fmt.Println("Téléphone non fourni")
}

// Itération sur la map
for key, value := range student {
    fmt.Printf("%s: %v\n", key, value)
}

5.4 Structures (Structs)

Les structures sont des collections de champs qui peuvent avoir différents types :

// Définition de structure
type Person struct {
    Name string
    Age  int
    City string
}

// Création d'instances de structure
person1 := Person{"Alice", 25, "New York"}
person2 := Person{
    Name: "Bob",
    Age:  30,
    City: "London",
}

// Accès aux champs
fmt.Println(person1.Name)
person1.Age = 26

6. Opérations et opérateurs

Go fournit un riche ensemble d’opérateurs pour divers calculs et comparaisons.

  • Opérateurs arithmétiques : +, -, *, /, % (modulo)
  • Opérateurs de comparaison : ==, !=, >, <, >=, <=
  • Opérateurs logiques : &&, ||, !
  • Opérateurs bit à bit : &, |, ^, <<, >>
  • Opérateurs d’affectation : =, +=, -=, *=, /=

6.1 Opérateurs arithmétiques

a, b := 10, 3

fmt.Printf("Addition : %d\n", a + b)      // 13
fmt.Printf("Soustraction : %d\n", a - b)   // 7
fmt.Printf("Multiplication : %d\n", a * b)  // 30
fmt.Printf("Division : %d\n", a / b)      // 3
fmt.Printf("Modulo : %d\n", a % b)      // 1

6.2 Opérateurs de comparaison

x, y := 5, 10

fmt.Printf("Égal : %t\n", x == y)     // false
fmt.Printf("Non égal : %t\n", x != y) // true
fmt.Printf("Supérieur à : %t\n", x > y)  // false
fmt.Printf("Inférieur à : %t\n", x < y)  // true

6.3 Opérateurs logiques

a, b := true, false

fmt.Printf("Opération ET : %t\n", a && b)  // false
fmt.Printf("Opération OU : %t\n", a || b)    // true
fmt.Printf("Opération NON : %t\n", !a)    // false

7. Contrôle de flux

Go fournit plusieurs instructions de contrôle de flux pour gérer l’exécution du programme.

7.1 Instructions if

age := 20
if age >= 18 {
    fmt.Println("Adulte")
} else if age >= 13 {
    fmt.Println("Adolescent")
} else {
    fmt.Println("Enfant")
}

// if avec instruction courte
if score := 85; score >= 90 {
    fmt.Println("Note : A")
} else if score >= 80 {
    fmt.Println("Note : B")
} else {
    fmt.Println("Note : C")
}

7.2 Boucles for

Go n’a qu’une seule construction de boucle : for

// Boucle for basique
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// Boucle de style while
count := 0
for count < 5 {
    fmt.Println(count)
    count++
}

// Boucle infinie
for {
    fmt.Println("Ceci s'exécutera indéfiniment")
    break // Utiliser break pour sortir
}

// Boucle range (pour les tranches, tableaux, maps)
fruits := []string{"pomme", "banane", "cerise"}
for index, fruit := range fruits {
    fmt.Printf("%d: %s\n", index, fruit)
}

7.3 Instructions switch

day := "Lundi"
switch day {
case "Lundi":
    fmt.Println("Début de la semaine")
case "Vendredi":
    fmt.Println("Le week-end approche")
case "Samedi", "Dimanche":
    fmt.Println("Week-end !")
default:
    fmt.Println("Jour ordinaire")
}

// Switch sans expression
score := 85
switch {
case score >= 90:
    fmt.Println("Note : A")
case score >= 80:
    fmt.Println("Note : B")
case score >= 70:
    fmt.Println("Note : C")
default:
    fmt.Println("Note : F")
}

8. Fonctions

Les fonctions en Go sont des citoyens de première classe et prennent en charge plusieurs valeurs de retour.

8.1 Fonctions de base

func greet(name string) string {
    return "Bonjour, " + name + " !"
}

// Appel de la fonction
message := greet("John")
fmt.Println(message)

8.2 Valeurs de retour multiples

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("impossible de diviser par zéro")
    }
    return a / b, nil
}

// Utilisation de valeurs de retour multiples
result, err := divide(10, 2)
if err != nil {
    fmt.Println("Erreur :", err)
} else {
    fmt.Println("Résultat :", result)
}

8.3 Valeurs de retour nommées

func calculateRectangle(width, height float64) (area float64, perimeter float64) {
    area = width * height
    perimeter = 2 * (width + height)
    return // retour nu
}

area, perimeter := calculateRectangle(5, 3)
fmt.Printf("Aire : %.2f, Périmètre : %.2f\n", area, perimeter)

8.4 Fonctions variadiques

func sum(numbers ...int) int {
    total := 0
    for _, num := range numbers {
        total += num
    }
    return total
}

fmt.Println(sum(1, 2, 3, 4))  // 10
fmt.Println(sum(5, 10, 15))   // 30

9. Pointeurs

Go a des pointeurs mais avec une syntaxe plus simple que C/C++ :

func modifyValue(x *int) {
    *x = *x * 2
}

func main() {
    value := 10
    fmt.Println("Avant :", value) // 10

    modifyValue(&value)
    fmt.Println("Après :", value)  // 20
}

10. Méthodes

Les méthodes sont des fonctions avec un argument récepteur :

type Rectangle struct {
    Width  float64
    Height float64
}

// Méthode avec récepteur de valeur
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Méthode avec récepteur de pointeur
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

rect := Rectangle{Width: 5, Height: 3}
fmt.Println("Aire :", rect.Area()) // 15

rect.Scale(2)
fmt.Println("Aire mise à l'échelle :", rect.Area()) // 60

11. Interfaces

Les interfaces définissent des signatures de méthode que les types peuvent implémenter :

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * 3.14159 * c.Radius
}

func printShapeInfo(s Shape) {
    fmt.Printf("Aire : %.2f, Périmètre : %.2f\n", s.Area(), s.Perimeter())
}

circle := Circle{Radius: 5}
printShapeInfo(circle)

12. Gestion des erreurs

Go utilise une gestion explicite des erreurs plutôt que des exceptions :

func readFile(filename string) (string, error) {
    data, err := os.ReadFile(filename)
    if err != nil {
        return "", fmt.Errorf("échec de la lecture du fichier %s: %w", filename, err)
    }
    return string(data), nil
}

content, err := readFile("example.txt")
if err != nil {
    fmt.Println("Erreur :", err)
    return
}
fmt.Println("Contenu :", content)

13. Concurrence avec les goroutines

Les goroutines sont des threads légers gérés par l’environnement d’exécution Go :

func worker(id int) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Travailleur %d: %d\n", id, i)
        time.Sleep(time.Millisecond * 100)
    }
}

func main() {
    // Démarrer plusieurs goroutines
    for i := 1; i <= 3; i++ {
        go worker(i)
    }

    // Attendre que les goroutines se terminent
    time.Sleep(time.Second)
    fmt.Println("Tous les travailleurs ont terminé")
}

14. Canaux (Channels)

Les canaux sont utilisés pour la communication entre goroutines :

func producer(ch chan<- int) {
    for i := 0; i < 5; i++ {
        ch <- i // Envoyer une valeur au canal
        time.Sleep(time.Millisecond * 100)
    }
    close(ch) // Fermer le canal une fois terminé
}

func consumer(ch <-chan int) {
    for value := range ch {
        fmt.Println("Reçu :", value)
    }
}

func main() {
    ch := make(chan int, 3) // Canal tamponné

    go producer(ch)
    consumer(ch)

    fmt.Println("Communication par canal terminée")
}

15. Opérations sur les fichiers

Go fournit des méthodes simples pour lire et écrire des fichiers :

// Lecture de fichiers
data, err := os.ReadFile("example.txt")
if err != nil {
    fmt.Println("Erreur de lecture du fichier :", err)
    return
}
fmt.Println("Contenu du fichier :", string(data))

// Écriture de fichiers
content := "Bonjour, Go !\n"
err = os.WriteFile("output.txt", []byte(content), 0644)
if err != nil {
    fmt.Println("Erreur d'écriture du fichier :", err)
    return
}
fmt.Println("Fichier écrit avec succès")

16. Packages et modules

Les modules Go gèrent les dépendances et les versions des packages :

// Importation de packages de la bibliothèque standard
import (
    "fmt"
    "math"
    "strings"
)

func main() {
    fmt.Println(math.Sqrt(16))        // 4
    fmt.Println(strings.ToUpper("go")) // GO
}

Pour créer votre propre package, créez un répertoire avec le nom de votre package et exportez les fonctions en capitalisant leurs noms.

17. Tests

Go a un support de test intégré :

// Dans le fichier math_test.go
package main

import "testing"

func TestAdd(t *testing.T) {
    result := add(2, 3)
    expected := 5
    if result != expected {
        t.Errorf("add(2, 3) = %d; attendu %d", result, expected)
    }
}

func add(a, b int) int {
    return a + b
}

Exécutez les tests avec : go test

18. Bonnes pratiques

  • Utilisez gofmt pour formater votre code
  • Suivez les conventions de nommage de Go (camelCase pour les variables, PascalCase pour les exports)
  • Gérez les erreurs explicitement
  • Utilisez les interfaces pour l’abstraction
  • Préférez la composition à l’héritage
  • Écrivez des tests complets
  • Utilisez la bibliothèque standard autant que possible

Ce tutoriel couvre les fonctionnalités essentielles de la programmation Go. Avec de la pratique, vous serez capable de créer des applications efficaces et concurrentes en utilisant les fonctionnalités puissantes de Go.